//
// Created by whz on 2022/5/22.
//

#include "../src/buffer/buffer_pool.h"
#include "../src/common/stop_watch.h"
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>

void alloc_time(BufferPool *bufferPool, int page_no) {
    StopWatch stopWatch;
    std::cout << "start test page[" << page_no << "]" << std::endl;
    for (int i = 0; i < 1; i++) {
        stopWatch.start();
        bufferPool->allocate(page_no);
        std::cout << "alloc_time:" << stopWatch.getElapsedTime() << "us" << std::endl;
    }

}

void release_time(BufferPool *bufferPool, int page_no) {
    PAGE *page = bufferPool->allocate(page_no);

    StopWatch stopWatch;
    stopWatch.start();
    bufferPool->release(page);
    std::cout << "release_time:" << stopWatch.getElapsedTime() << "us" << std::endl;

}

void test_man(BufferPool *bufferPool) {
    alloc_time(bufferPool, -1);
    alloc_time(bufferPool, -1);
    alloc_time(bufferPool, -1);
}

void fread1(PAGE *block, off_t offset) {
    StopWatch stopWatch;
    int fd = open(PATH_COMMIT, O_RDONLY);
    std::cout << "time:" << stopWatch.getElapsedTime() << "us" << std::endl;
    stopWatch.start();
    int len = lseek(fd, 0, SEEK_END);
    char *buffer = (char *) mmap(nullptr, len, PROT_READ, MAP_SHARED, fd, 0);
    std::cout << "time:" << stopWatch.getElapsedTime() << "us" << std::endl;
    close(fd);
    stopWatch.start();
    memcpy(block, buffer + offset, sizeof(PAGE));
    std::cout << "time:" << stopWatch.getElapsedTime() << "us" << std::endl;
    stopWatch.start();
//    block = (PAGE *) (buffer + offset);

    munmap(buffer,len);
    std::cout << "time:" << stopWatch.getElapsedTime() << "us" << std::endl;
}


void serialized(PAGE *block, size_t page_no) {
    StopWatch stopWatch;

    off_t offset = page_no * sizeof(PAGE);
    fread1(block, offset);
    std::cout << "serialized page[" << page_no << "]:" << stopWatch.getElapsedTime() << "us" << std::endl;

}

void deserialized(PAGE *block, size_t page_no) {
    StopWatch stopWatch;

    std::ofstream fout(PATH_COMMIT, std::ios::in | std::ios::out | std::ios::binary);
    off_t offset = page_no * sizeof(PAGE);
    fout.seekp(offset);
    fout.write((char *) block, sizeof(PAGE));
    fout.close();

    std::cout << "deserialized page[" << page_no << "]:" << stopWatch.getElapsedTime() << "us" << std::endl;
}

void test_save() {
    PAGE *page1 = new PAGE();
    PAGE *page2 = new PAGE();
    page1->file_header.setFilePagePrev(100);
    page1->file_header.setFilPageNext(1010);
    page1->file_header.setFilPageParent(23213);

    deserialized(page1, 5);
    deserialized(page1, 6);
    deserialized(page1, 7);
    serialized(page2, 7);
    serialized(page2, 50);
//    fwrite(page1, 2);
//    fread1(page2, 3 * PAGE_SIZE);
//    page1->file_header.setFilPageNext(1);
    std::cout << page1->file_header.getFilPageNext() << std::endl << page2->file_header.getFilPageNext() << std::endl;
    std::cout << page1->file_header.getFilPageParent() << std::endl << page2->file_header.getFilPageParent()
              << std::endl;
}

char main() {
//    auto bufferPool = BufferPool::getInstance();
//    int ch;
////    while (ch = getchar()) {
////        if (ch == '\n') {
////            continue;
////        }
////        if (ch == 'p') {
////            break;
////        }
////        std::cout << ch;
////        alloc_time(bufferPool.get(), ch - 'a');
////    }
//    PAGE *page = bufferPool->get_root();
//    std::cout << page->getPageNo() << std::endl;
//    page->setPageNo(12);
//    bufferPool->destroy();
    test_save();
//    PAGE *page = bufferPool->get_root();
//    std::cout << page->getPageNo() << std::endl;
//    page->setPageNo(5);
    //buffer_pool用法
//    bufferPool->allocate();
//    (*bufferPool).allocate();
    return 0;

}